import { promises as fs } from 'fs';
import path from 'path';
import YAML from 'yaml';

const ROOT = path.resolve(process.cwd());
const ARTICLES_DIR = path.join(ROOT, 'articles');
const PUBLIC_DIR = path.join(ROOT, 'public');

const SITE_URL = process.env.SITE_URL || 'https://example.com';
const SITE_TITLE = process.env.SITE_TITLE || '有追求的开发者';
const SITE_DESC = process.env.SITE_DESC || '  ';

function ensureLeadingSlash(p) { return p.startsWith('/') ? p : '/' + p; }

function parseFrontmatter(markdown) {
  if (markdown.startsWith('---')) {
    const end = markdown.indexOf('\n---', 3);
    if (end !== -1) {
      const fmBlock = markdown.slice(3, end).replace(/^\n/, '');
      const content = markdown.slice(end + 4).replace(/^\s*\n/, '');
      let data = {};
      try { data = YAML.parse(fmBlock) || {}; } catch {}
      return { data, content };
    }
  }
  return { data: {}, content: markdown };
}

function parseTitle(markdownContent) {
  const lines = markdownContent.split(/\r?\n/);
  for (const line of lines) {
    const m = /^#\s+(.+)/.exec(line.trim());
    if (m) return m[1].trim();
  }
  return (lines.find(l => l.trim().length > 0)?.trim().slice(0, 60)) || '未命名文章';
}

function stripMarkdown(markdownContent) {
  let text = markdownContent.replace(/```[\s\S]*?```/g, '');
  text = text.replace(/<[^>]+>/g, '');
  text = text.replace(/!\[[^\]]*\]\([^)]*\)/g, '');
  text = text.replace(/\[[^\]]*\]\([^)]*\)/g, '');
  text = text.replace(/^#{1,6}\s+/gm, '');
  text = text.replace(/[*_`>#-]+/g, ' ');
  return text.replace(/\s+/g, ' ').trim();
}

function toRfc822(dateStr) {
  const d = new Date(dateStr);
  if (isNaN(d.getTime())) return new Date().toUTCString();
  return d.toUTCString();
}

async function readArticles() {
  const entries = await fs.readdir(ARTICLES_DIR, { withFileTypes: true });
  const files = entries.filter(e => e.isFile() && e.name.endsWith('.md'));
  const posts = [];
  for (const f of files) {
    const filePath = path.join(ARTICLES_DIR, f.name);
    const raw = await fs.readFile(filePath, 'utf8');
    const { data, content } = parseFrontmatter(raw);
    const title = (typeof data.title === 'string' && data.title.trim()) || parseTitle(content);
    const slug = f.name.replace(/\.md$/, '');
    const date = typeof data.date === 'string' ? data.date : undefined;
    const plain = stripMarkdown(content);
    const excerpt = plain.slice(0, 160);
    const url = new URL(`/post/${encodeURIComponent(slug)}`, SITE_URL).toString();
    posts.push({ slug, title, date, excerpt, url });
  }
  posts.sort((a, b) => {
    if (a.date && b.date) return b.date.localeCompare(a.date);
    if (a.date) return -1;
    if (b.date) return 1;
    return a.title.localeCompare(b.title, 'zh-CN');
  });
  return posts;
}

function escapeXml(str) {
  return String(str)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&apos;');
}

async function generateRSS(posts) {
  const now = new Date().toUTCString();
  const rssItems = posts.map(p => `\n    <item>
      <title>${escapeXml(p.title)}</title>
      <link>${escapeXml(p.url)}</link>
      <guid isPermaLink="true">${escapeXml(p.url)}</guid>
      <pubDate>${toRfc822(p.date || now)}</pubDate>
      <description>${escapeXml(p.excerpt)}</description>
    </item>`).join('');

  const rss = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>${escapeXml(SITE_TITLE)}</title>
    <link>${escapeXml(SITE_URL)}</link>
    <description>${escapeXml(SITE_DESC)}</description>
    <lastBuildDate>${now}</lastBuildDate>${rssItems}
  </channel>
</rss>\n`;
  await fs.writeFile(path.join(PUBLIC_DIR, 'rss.xml'), rss, 'utf8');
}

async function generateSitemap(posts) {
  const urls = [SITE_URL.replace(/\/$/, '/')];
  const urlset = posts.map(p => `  <url><loc>${escapeXml(p.url)}</loc>${p.date ? `<lastmod>${escapeXml(p.date)}</lastmod>` : ''}</url>`).join('\n');
  const xml = `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url><loc>${escapeXml(urls[0])}</loc></url>
${urlset}
</urlset>\n`;
  await fs.writeFile(path.join(PUBLIC_DIR, 'sitemap.xml'), xml, 'utf8');
}

async function generateRobots() {
  const robots = `User-agent: *\nAllow: /\nSitemap: ${SITE_URL.replace(/\/$/, '')}/sitemap.xml\n`;
  await fs.writeFile(path.join(PUBLIC_DIR, 'robots.txt'), robots, 'utf8');
}

async function main() {
  await fs.mkdir(PUBLIC_DIR, { recursive: true });
  const posts = await readArticles();
  await generateRSS(posts);
  await generateSitemap(posts);
  await generateRobots();
  console.log(`Generated rss.xml, sitemap.xml and robots.txt to public/ (posts: ${posts.length})`);
}

main().catch(err => { console.error(err); process.exit(1); });

